/*
	DHD SENT for GarrysMod10
	Copyright (C) 2007  aVoN

	This program is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

include("shared.lua")
ENT.RenderGroup = RENDERGROUP_OPAQUE -- This FUCKING THING avoids the clipping bug I have had for ages since stargate BETA 1.0. DAMN!

--################# Draw @aVoN
function ENT:Draw()
	self.Entity:DrawModel();
	local a = self.Entity:GetAngles();
	-- ################# Get the chevrons
	local address = self.Entity:GetNWString("ADDRESS"):TrimExplode(",");
	-- ################# Draw keyboard - Idea of how to use the cam3D2D stuff comes from Night-Eagles Computer SENT. Thank god, you coded it ;)
	local btn;
	if((LocalPlayer():GetShootPos() - self.Entity:LocalToWorld(self.ChevronPositions.DIAL)):Length() <= 90) then
		btn = self:GetCurrentButton(LocalPlayer());
	end
	local count = #address;
	-- Draw near buttons
	local button_angle = 20; -- Maximum distant-angle of a button to get drawn - High value = massive (clientside)lags, because the SENT will calculate vector/matrix multiplication - and this is very CPU heavy
	local btns = {};
	if(not self.Entity:GetNWBool("Busy",false)) then
		if(btn and btn ~= "DIAL" or count > 6) then
			btns = self:GetCurrentButton(LocalPlayer(),button_angle);
		end
	end
	-- ################# Lower the alpha for buttons when 6 are dialled to make the user clear to press chevron 7 now
	local alpha = 180;
	if(count == 6) then
		alpha = 100;
		if(not table.HasValue(address,"#")) then
			table.insert(btns,{button="#",angle=0});
		end
	end
	for _,v in pairs(address) do
		if(v ~= "" and v ~= "DIAL" and not v:find(",")) then
			table.insert(btns,{button=tonumber(v) or v,angle=0});
		end
	end
	-- ################# Draw buttons
	for _,v in pairs(btns) do
		if(v.button ~= "DIAL") then
			if(count < 7 or table.HasValue(address,tostring(v.button))) then
				local a = self.Entity:GetAngles();
				local p = self.Entity:LocalToWorld(self.ChevronPositions[v.button]-Vector(0,0,1)); -- Position of chevron
				local d = self.Entity:LocalToWorld(self.ChevronPositions[v.button]-self.ChevronPositions.DIAL)-self.Entity:GetPos(); -- Direction from the DHD's center to the chevron
				-- Yaw Rotate, or the buttons face to the wrong direction
				a:RotateAroundAxis(self.Entity:GetUp(),90);
				-- Pitch angle - Make the buttons face better to the surface
				local pitch = self.Entity:GetForward():Dot(d:Normalize());
				a:RotateAroundAxis(self.Entity:GetRight(),-15*pitch); -- Correct little pitch for texturesurface
				-- Fading color for the buttons pendent from their distance
				local color = Color(255,255,255,alpha*(1-v.angle/button_angle));
				-- When 6 buttons are dialled, highligh chevron 7 white. Furthermore the alpha (watch above) is lowered from 255 to 100 for all other buttons, so even noobs will find out, to press chevron 7
				if((count == 6 and v.button == "#" and not table.HasValue(address,"#")) or count > 6 or table.HasValue(address,tostring(v.button))) then
					color = Color(255,255,255,255);
				end
				-- ################# Highlight current button aimed at orange or gray when already dialled
				if(v.button == btn and count < 7) then
					local sel = false;
					if(count < 6 or v.button == "#") then
						if(table.HasValue(address,tostring(btn))) then
							sel = true;
						end
						-- ################# Button already dialled - Make it white
						if(sel) then
							color = Color(255,255,255,255);
						else
							local brightness = 55;
							color = (self.Color.chevron.." 255"):TrimExplode(" ");
							color[1] = color[1]+brightness;
							color[2] = color[2]+brightness;
							color[3] = color[3]+brightness;
							color = Color(unpack(color));
						end
					end
				end
				-- ################# Make C7 blink!
				if(count == 6) then
					if(v.button == "#") then
						self.StartedBlinking = self.StartedBlinking or CurTime();
						color.a = math.Clamp(255*(1+math.cos((CurTime()-self.StartedBlinking)*math.pi))/2,20,255);
					end
				else
					self.StartedBlinking = nil;
				end
				-- ################# Draw the buttons
				cam.Start3D2D(p+d:Normalize()*0.5,a,.3);
					draw.SimpleText(v.button,"Default",0,0,color,1,1);
				cam.End3D2D();
			end
		end
	end
end


--##################################
--#### VGUI/Dial Menu
--##################################

-- ################# Opens the Dialling Dialoge @aVoN
local VGUI;
local DHD;
-- FIXME: Rewrite the ADDRES and NWInt part (MUCH BUGGY!)
usermessage.Hook("StarGate.OpenDialMenuDHD",
	function(data)
		local e = data:ReadEntity();
		if(ValidEntity(e) and e:GetClass():find("stargate_")) then
			if(not VGUI) then VGUI = vgui.Create("SControlePanelDHD") end;
			VGUI:SetVisible(true);
			VGUI:SetEntity(e);
			DHD = data:ReadEntity();
			-- FIXME: THAT BELOW HAS TO BE COMPLETELY REWRITTEN!
			VGUI.OnTextChanged = function(SControlePanelDHD)
				local value = (SControlePanelDHD:GetValue() or ""):upper();
				-- Have We added or removed any chars?
				local chevrons = DHD:GetNWString("ADDRESS",""):upper():gsub(",",""):Trim();
				local bugfix;
				local symbol;
				if(chevrons:len() < value:len()) then -- Current chevrons are less than the new value
					symbol = value:gsub("["..chevrons.." ]?",""); -- ADD a chevron
					bugfix = table.concat((chevrons..symbol):TrimExplode(""),","); -- for the BUGFIX below
				else
					symbol = chevrons:gsub("["..value.." ]?",""); -- REMOVE a chevron
					bugfix = table.concat((chevrons:gsub(symbol,"")):TrimExplode(""),","); -- for the BUGFIX below
				end
				if(symbol and symbol:Trim():len() == 1) then
					-- Fixes a multiplayer bug, where latency causes a too late update of the chevrons clientside (throws errors)
					DHD:SetNWString("ADDRESS",bugfix);
					LocalPlayer():ConCommand("_StarGate.DHD.AddSymbol "..DHD:EntIndex().." "..symbol);
				end
			end
		end
	end
);

-- ################# Closes the dialling Dialoge @aVoN
usermessage.Hook("StarGate.DialMenuDHDClose",
	function(data)
		if(VGUI and VGUI:IsValid()) then
			VGUI:SetVisible(false);
		end
	end
);

-- ################# Screen clicking code @aVoN
hook.Add("GUIMousePressed","StarGate.DHD.GUIMousePressed",
	function(_,dir)
		if(ValidEntity(DHD)) then
			local p = LocalPlayer();
			local trace = util.QuickTrace(p:GetShootPos(),dir*1024,p);
			if(trace.Entity == DHD) then
				local btn = DHD:GetCurrentButton(p);
				if(btn) then
					p:ConCommand("_StarGate.DHD.AddSymbol "..DHD:EntIndex().." "..btn);
					-- ######### Add/Remove symbols
					if(btn ~= "#" and btn ~= "DIAL") then
						local chevrons = DHD:GetNWString("ADDRESS",""):upper():TrimExplode(",");
						btn = tostring(btn):upper();
						local add = true;
						for k,v in pairs(chevrons) do
							if(v == btn) then
								chevrons[k] = nil;
								add = false;
							end
							-- Should never be addedto the VGUI
							if(v == "#" or v == "DIAL") then
								chevrons[k] = nil;
							end
						end
						if(add and #chevrons < 6) then
							table.insert(chevrons,btn);
						end
						VGUI:SetText(table.concat(table.ClearKeys(chevrons)));
					end
				end
			end
		end
	end
);